/*
  Copyright (C) 2011, Kyungjoo Kim
  
  This file is part of LINAL (LINear ALgebra)
  
  All rights reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  
  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
  
  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  Also add information on how to contact you by electronic and paper mail.
  
  
  Kyungjoo Kim
  iamkyungjoo@gmail.com
*/
#ifndef LINAL_DEVICE_HOST_MANAGER_HXX
#define LINAL_DEVICE_HOST_MANAGER_HXX

namespace linal {
  namespace host {
    
    typedef struct FLA_Obj_view FLA_Obj;
    typedef class Manager_* Manager;

    // -------------------------------------------------------------- 
    // ** Abstract interfaces for the devices
    // - group 0 is reserved for the host device.
    class Manager_ : public Device_ {

    private:
    protected:
    public:
      Manager_() : Device_(0, 0, LINAL_DEVICE_HOST) { }  
      virtual ~Manager_() { }

      inline virtual void critical_begin() { }
      inline virtual void critical_end() { }
      inline virtual void invalidate(FLA_Obj &A) { }

      // devices are pre-selected by the mapping policy 2d heuristic distribution 
      // or 1d distribution.
      virtual Int_ chol_nopiv ( Int_ uplo, FLA_Obj &A ) {
        this->chol_nopiv_stat();
        return internal::chol_nopiv( uplo, A );
      }
      virtual Int_ chol_piv   ( Int_ uplo, FLA_Obj &A,  FLA_Obj &p ) {
        this->chol_piv_stat();
        return internal::chol_piv( uplo, A, p );
      }
      virtual Int_ ldl_nopiv  ( Int_ uplo, FLA_Obj &A ) {
        this->ldl_nopiv_stat();
        return internal::ldl_nopiv( uplo, A );
      }
      virtual Int_ ldl_piv    ( Int_ uplo, FLA_Obj &A,  FLA_Obj &p ) {
        this->ldl_piv_stat();
        return internal::ldl_piv( uplo, A, p );
      }
        
      virtual Int_ lu_nopiv   ( FLA_Obj &A ) {
        this->lu_nopiv_stat();
        return internal::lu_nopiv( A );
      }
      virtual Int_ lu_piv     ( FLA_Obj &A, FLA_Obj &p ) {
        this->lu_piv_stat();
        return internal::lu_piv( A, p );
      }
        
      virtual Int_ qr         ( FLA_Obj &A, FLA_Obj &T ) {
        this->qr_stat();
        return internal::qr( A, T );
      }
        
      virtual Int_ gemm( Int_ transa, Int_ transb,
                         FLA_Obj &alpha,  FLA_Obj &A,  FLA_Obj &B,
                         FLA_Obj &beta,   FLA_Obj &C ) {
        this->gemm_stat();
        return internal::gemm( transa, transb, alpha, A, B, beta, C );
      }
      virtual Int_ herk( Int_ uplo, Int_ trans,
                         FLA_Obj &alpha,  FLA_Obj &A,
                         FLA_Obj &beta,   FLA_Obj &C ) {
        this->herk_stat();
        return internal::herk( uplo, trans, alpha, A, beta, C );
      }
      virtual Int_ trmm( Int_ side, Int_ uplo, Int_ trans, Int_ diag,
                         FLA_Obj &alpha,  FLA_Obj &A,  FLA_Obj &B ) {
        this->trmm_stat();
        return internal::trmm( side, uplo, trans, diag, alpha, A, B );
      }
      virtual Int_ trsm( Int_ side, Int_ uplo, Int_ trans, Int_ diag,
                         FLA_Obj &alpha,  FLA_Obj &A,  FLA_Obj &B ) {
        this->trsm_stat();
        return internal::trsm( side, uplo, trans, diag, alpha, A, B );
      }
      virtual Int_ syrk( Int_ uplo, Int_ trans,
                         FLA_Obj &alpha,  FLA_Obj &A,
                         FLA_Obj &beta,   FLA_Obj &C ) {
        this->syrk_stat();
        return internal::syrk( uplo, trans, alpha, A, beta, C );
      }
    };
  }
}

#endif
